/*
 * Copyright (c) 2020-2021 imlzw@vip.qq.com jweb.cc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cc.jweb.adai.web.system.generator.model;

import cc.jweb.boot.annotation.Column;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import cc.jweb.adai.web.system.generator.model.code.GeneratorConfig;
import io.jboot.db.annotation.Table;
import io.jboot.db.model.JbootModel;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 代码生成模型
 */
@Table(tableName = "sys_generator_model", primaryKey = "generator_id")
public class GeneratorModel extends JbootModel<GeneratorModel>{
    public static final GeneratorModel dao = new GeneratorModel().dao();
    private static final long serialVersionUID = -1595214825779L;
    private static Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").registerTypeAdapter((new TypeToken<Map<String, Object>>() {
    }).getType(), new MapTypeAdapter()).create();

    /**
     * 生成编号
     */
    @Column(field = "generator_id")
    private int generatorId;

    /**
     * 生成名称
     */
    @Column(field = "generator_name")
    private String generatorName;

    /**
     * 关联模板id
     */
    @Column(field = "template_id")
    private String templateId;

    /**
     * 生成器配置
     */
    @Column(field = "generator_config")
    private String generatorConfig;

    public int getGeneratorId() {
        return get("generator_id");
    }

    public GeneratorModel setGeneratorId(int generatorId) {
        set("generator_id", generatorId);
        return this;
    }

    public String getGeneratorName() {
        return get("generator_name");
    }

    public GeneratorModel setGeneratorName(String generatorName) {
        set("generator_name", generatorName);
        return this;
    }

    public String getTemplateId() {
        return get("template_id");
    }

    public GeneratorModel setTemplateId(String templateId) {
        set("template_id", templateId);
        return this;
    }

    public String getGeneratorConfig() {
        return get("generator_config");
    }

    public GeneratorModel setGeneratorConfig(String generatorConfig) {
        set("generator_config", generatorConfig);
        return this;
    }

    public GeneratorConfig toGeneratorConfig() {
        GeneratorConfig generatorConfig = null;
        try {
            generatorConfig = gson.fromJson(this.getGeneratorConfig(), GeneratorConfig.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (generatorConfig == null) {
            generatorConfig = new GeneratorConfig();
        }
        return generatorConfig;
    }

    /**
     * 重载json转换类,主要目的是为了防止转为map时integer型变量错误地转换为Dobule型变量
     */
    public static class MapTypeAdapter extends TypeAdapter<Object> {

        private TypeAdapter<Object> defaultAdapter = new Gson().getAdapter(Object.class);

        @Override
        public Object read(JsonReader in) throws IOException {
            JsonToken token = in.peek();
            switch (token) {
                case BEGIN_ARRAY:
                    List<Object> list = new ArrayList<Object>();
                    in.beginArray();
                    while (in.hasNext()) {
                        list.add(read(in));
                    }
                    in.endArray();
                    return list;
                case BEGIN_OBJECT:
                    Map<String, Object> map = new LinkedTreeMap<String, Object>();
                    in.beginObject();
                    while (in.hasNext()) {
                        map.put(in.nextName(), read(in));
                    }
                    in.endObject();
                    return map;

                case STRING:
                    return in.nextString();
                case NUMBER:
                    /**
                     * 改写数字的处理逻辑，将数字值分为整型与浮点型。
                     * 流程（规则）:
                     * 1.先读取字符串，并转为为double类型
                     * 2.如果字符串包含小数点,则直接返回double类型
                     * 3.如果数值大于Long型的最大值，则返回double类型
                     * 4.如果数值大于Integer型的最大值，则返回long类型
                     */
                    String temp = in.nextString();
                    double dbNum = Double.parseDouble(temp);
                    if (temp.contains(".")) {
                        return dbNum;
                    }
                    // 数字超过long的最大值，返回浮点类型
                    if (dbNum > Long.MAX_VALUE) {
                        return dbNum;
                    }
                    if (dbNum > Integer.MAX_VALUE) {
                        return (long) dbNum;
                    }
                    return new Double(dbNum).intValue();
                case BOOLEAN:
                    return in.nextBoolean();
                case NULL:
                    in.nextNull();
                    return null;

                default:
                    throw new IllegalStateException();
            }
        }

        @Override
        public void write(JsonWriter out, Object value) throws IOException {
            /*
             * 坑:如果不写,内部类包含对应的成员变量时将无法转化为json串
             * 这里使用原生gson的typeAdapter来代理进行解析,希望有更好的解决方案
             */
            defaultAdapter.write(out, value);
        }

    }
}
